﻿using ChuanYe.WorkLogManagement.EF.SqlServer;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using System.Transactions;
using System;
using System.Linq;
using ChuanYe.WorkLogManagement.Model;

namespace ChuanYe.WorkLogManagement.BLL
{
    public class WorkInfoBLL
    {
        #region 构造单例
        private WorkInfoBLL() { }
        private static WorkInfoBLL _instance;
        public static WorkInfoBLL Instance
        {
            get
            {
                return _instance ?? (_instance = new WorkInfoBLL());
            }
        }
        #endregion

        public List<WorkInfoModel> Get(int fromUserID,int toUserID,DateTime? startTime,DateTime? endTime, int finshState=0, int level=0)
        {
            var isSee = false;

            if (startTime == null)
            {
                startTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59"));
            }
            else {
                startTime = Convert.ToDateTime(startTime.Value.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(endTime.Value.ToString("yyyy-MM-dd 23:59:59"));
            }

            if (fromUserID == 0 && toUserID == 0)
            {
                return new List<WorkInfoModel>();
            }if (fromUserID == toUserID)
            {
                isSee = true;
            }

            using (WorkLogContext context = new WorkLogContext())
            {
                var linq = from a in context.WorkInfo
                           join b in context.UserInfo on a.UserID equals b.UserID
                           into c 
                           let d=c.FirstOrDefault()
                           select new WorkInfoModel{
                               GUID= a.GUID,
                               IsPrivate=a.IsPrivate,
                               Level= a.Level,
                               WorkContent = (a.IsPrivate==true && isSee==false) ? "内容已设置为 【私有】 ":a.WorkContent,
                               FinshContent = (a.IsPrivate == true && isSee == false) ? "内容已设置为 【私有】" : a.FinshContent,
                               FinshState=a.FinshState,
                               Remark = a.IsPrivate == true && isSee == false ? "内容已设置为 【私有】" : a.Remark,
                               AddTime=a.AddTime,
                               UserID=a.UserID,
                               RowNumber=a.RowNumber,
                               RealName=d.RealName,
                               AccountName=d.AccountName,
                               Month=a.Month,
                               Day=a.Day,
                           };
                if (toUserID > 0)
                {
                    linq = linq.Where(p => p.UserID== toUserID);
                }
                if (finshState > 0)
                {
                    linq = linq.Where(p => p.FinshState == finshState);
                }
                if (level> 0)
                {
                    linq = linq.Where(p => p.Level ==level);
                }

                linq = linq.Where(p=>p.AddTime >=startTime && p.AddTime<=endTime);
                linq = linq.OrderBy(o=>o.AddTime);
                return linq.ToList();
            }
        }

        public void Add(List<WorkInfo> infos)
        {
            using (WorkLogContext context = new WorkLogContext())
            {
                using (TransactionScope trans = new TransactionScope())
                {
                    foreach (var item in infos)
                    {
                        context.WorkInfo.Add(item);
                        context.Entry<WorkInfo>(item).State = EntityState.Added;
                    }
                    context.SaveChanges();
                    trans.Complete();
                }
            }
        }

        public string AddOrUpdate(WorkInfo info)
        {
            string guid = string.Empty;
            using (WorkLogContext context = new WorkLogContext())
            {
                if (!string.IsNullOrEmpty(info.GUID))
                {
                    var exist = context.WorkInfo.Where(p => p.GUID == info.GUID).FirstOrDefault();
                    if (exist == null)
                    {
                        return "";
                    }
                    exist.WorkContent = info.WorkContent;
                    exist.Day = info.Day;
                    exist.Month = info.Month;
                    exist.FinshState = info.FinshState;
                    exist.FinshContent = info.FinshContent;
                    exist.IsPrivate = info.IsPrivate;
                    exist.UserID = info.UserID;
                    exist.Level = info.Level;
                    exist.Remark = info.Remark;
                    exist.RowNumber = info.RowNumber;
                    exist.AddTime = info.AddTime;
                    context.WorkInfo.Add(exist);
                    context.Entry<WorkInfo>(exist).State = EntityState.Modified;
                    guid = info.GUID;
                }
                else
                {
                    info.GUID = System.Guid.NewGuid().ToString();
                    context.WorkInfo.Add(info);
                    context.Entry<WorkInfo>(info).State = EntityState.Added;
                    guid = info.GUID;
                }
                context.SaveChanges();
            }
            return guid;
        }

        public int Remove(string guid)
        {
            using (WorkLogContext context = new WorkLogContext())
            {
                var exist = context.WorkInfo.Where(p => p.GUID == guid).FirstOrDefault();
                if (exist == null)
                {
                    return 0;
                }
                context.WorkInfo.Add(exist);
                context.Entry<WorkInfo>(exist).State = EntityState.Deleted;
                context.SaveChanges();
                return 1;
            }
        }

        public List<dynamic> GetWorkToSelfAndChild(int userID, string keyword,DateTime? startTime, DateTime? endTime)
        {
            if (startTime == null)
            {
                startTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59"));
            }
            else
            {
                startTime = Convert.ToDateTime(startTime.Value.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(endTime.Value.ToString("yyyy-MM-dd 23:59:59"));
            }
            using (WorkLogContext context = new WorkLogContext())
            {
                var list = new List<dynamic>();
                #region 由 移动端 无法实现 后台代实现
                var slefUserLinq = from a in context.UserInfo
                                   join e in context.DepartmentInfo on a.DepartmentID equals e.DepartmentID
                                   into f
                                   let g = f.FirstOrDefault()
                                   join k in context.PositionInfo on a.PositionID equals k.PositionID
                                   into l
                                   let m = l.FirstOrDefault()
                                   select new
                                   {
                                       SlefID = a.UserID,
                                       ChilderID = a.UserID,
                                       a.RealName,
                                       a.PositionID,
                                       g.DepartmentID,
                                       g.DepartmentName,
                                       a.AccountName,
                                   };
                if (userID > 0)
                {
                    slefUserLinq = slefUserLinq.Where(p => p.SlefID == userID);
                }
                var slefUserWorkLinq= from a in context.WorkInfo
                                      join b in context.UserInfo on a.UserID equals b.UserID
                                      into c
                                      let d = c.FirstOrDefault()
                                      join e in slefUserLinq on a.UserID equals e.ChilderID
                                      into f
                                      let g = f.FirstOrDefault()
                                      select new WorkInfoModel
                                      {
                                          GUID = a.GUID,
                                          IsPrivate = a.IsPrivate,
                                          Level = a.Level,
                                          WorkContent = a.WorkContent,
                                          FinshState=a.FinshState,
                                          FinshContent = a.FinshContent,
                                          Remark =a.Remark,
                                          AddTime = a.AddTime,
                                          UserID = a.UserID,
                                          RowNumber = a.RowNumber,
                                          RealName = d.RealName,
                                          AccountName = d.AccountName,
                                          Month = a.Month,
                                          Day = a.Day,
                                      };

                var slefUserList = slefUserLinq.ToList();
                if (!string.IsNullOrEmpty(keyword))
                {
                    slefUserWorkLinq = slefUserWorkLinq.Where(p => p.RealName.Contains(keyword) || p.AccountName == keyword || p.WorkContent.Contains(keyword));
                }
                slefUserWorkLinq = slefUserWorkLinq.Where(p => p.AddTime >= startTime && p.AddTime <= endTime);
                var slefWorkList = slefUserWorkLinq.ToList();
                foreach (var item in slefUserList)
                {
                    var existWorkList = slefWorkList.Where((WorkInfoModel p) => p.UserID == item.ChilderID).OrderBy(o => o.AddTime).ToList();
                    
                    var info = new
                    {
                        UserID = item.ChilderID,
                        DepartmentID = item.DepartmentID,
                        DepartmentName = item.DepartmentName,
                        PositionID = item.PositionID,
                        PowerID = 0,
                        RealName = item.RealName,
                        WorkList = existWorkList,
                    };
                    list.Add(info);
                }
              
                #endregion 

                var userLinq = from a in context.UserPowerInfo
                           join b in context.UserInfo on a.ChilderID equals b.UserID
                           into c
                           let d = c.FirstOrDefault()
                           join e in context.DepartmentInfo on d.DepartmentID equals e.DepartmentID
                           into f
                           let g = f.FirstOrDefault()
                           join k in context.PositionInfo on d.PositionID equals k.PositionID
                           into l
                           let m = l.FirstOrDefault()
                           select new
                           {
                               SlefID = a.UserID,
                               a.ChilderID,
                               a.PowerID,
                               d.RealName,
                               d.PositionID,
                               g.DepartmentID,
                               g.DepartmentName,
                               d.AccountName,
                           };
                if (userID > 0)
                {
                    userLinq = userLinq.Where(p => p.SlefID == userID);
                }

                if (!string.IsNullOrEmpty(keyword))
                {
                    userLinq = userLinq.Where(p => p.RealName.Contains(keyword) || p.AccountName== keyword);
                }

                var workLinq=from a in context.WorkInfo
                           join b in context.UserInfo on a.UserID equals b.UserID
                           into c
                           let d = c.FirstOrDefault()
                           join e in userLinq on  a.UserID equals e.ChilderID
                           into f
                           let g=f.FirstOrDefault()
                           select new WorkInfoModel
                           {
                               GUID = a.GUID,
                               IsPrivate = a.IsPrivate,
                               Level = a.Level,
                               FinshState=a.FinshState,
                               WorkContent = (a.IsPrivate == true ) ? "内容已设置为 【私有】 " : a.WorkContent,
                               FinshContent = (a.IsPrivate == true )? "内容已设置为 【私有】" : a.FinshContent,
                               Remark = (a.IsPrivate == true) ? "内容已设置为 【私有】" : a.Remark,
                               AddTime = a.AddTime,
                               UserID = a.UserID,
                               RowNumber = a.RowNumber,
                               RealName = d.RealName,
                               AccountName = d.AccountName,
                               Month = a.Month,
                               Day = a.Day,
                           };

                var userList = userLinq.ToList();
                workLinq = workLinq.Where(p => p.AddTime >= startTime && p.AddTime <= endTime);
                var workList = workLinq.ToList();

                foreach (var item in userList)
                {
                    var existWorkList = workList.Where((WorkInfoModel p) => p.UserID == item.ChilderID).OrderBy(o=>o.AddTime).ToList();
                    var info = new {
                        UserID = item.ChilderID,
                        DepartmentID=item.DepartmentID,
                        DepartmentName=item.DepartmentName,
                        PositionID= item.PositionID,
                        PowerID=item.PowerID,
                        RealName=item.RealName,
                        WorkList= existWorkList,
                    };
                    list.Add(info);
                }
                return list;
            }

        }

        public List<dynamic> GetBasicDropDownList()
        {
            List<WorkLevelModel> levelList = GetLevelList();
            List<dynamic> finshStateList = new List<dynamic>();
            finshStateList.Add(new { State = 1, Name = "完成" });
            finshStateList.Add(new { State = 2, Name = "未完成" });
            finshStateList.Add(new { State = 100, Name = "其他" });

            List<dynamic> data = new List<dynamic>();
            data.Add(new
            {
                Key = "Level",
                Value = levelList,
                Remark = "日志级别"
            });

            data.Add(new
            {
                Key = "FinshState",
                Value = finshStateList,
                Remark = "日志完成状态"
            });
            return data;
        }

        public List<WorkLevelModel> GetLevelList() 
        {
            List<WorkLevelModel> levelList = new List<WorkLevelModel>();
            levelList.Add(new WorkLevelModel  { Level = 4, Name = "非常重要" });
            levelList.Add(new WorkLevelModel  { Level = 3, Name = "重要" });
            levelList.Add(new WorkLevelModel { Level = 2, Name = "一般" });
            levelList.Add(new WorkLevelModel { Level = 1, Name = "暂不关注" });
            return levelList;
        }

        public dynamic GetNext3DaysWork(int userID)
        {
            var startTime =Convert.ToDateTime(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd 00:00:00"));
            var endTime = Convert.ToDateTime(DateTime.Now.AddDays(1+2).ToString("yyyy-MM-dd 23:59:59"));
            using (WorkLogContext context = new WorkLogContext())
            {
                var list = context.WorkInfo.Where(p => p.UserID == userID && p.AddTime>= startTime && p.AddTime <= endTime)
                    .OrderBy(p=>p.AddTime)
                    .ToList();
                return list;
            }
        }

        public dynamic Statistics(DateTime? startTime, DateTime? endTime, int finshState, int level, int userID)
        {
            var list = new List<dynamic>();

            if (startTime == null && endTime == null)
            {
                startTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59"));
            }
            else if (startTime == null && endTime != null)
            {
                startTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(endTime.Value.ToString("yyyy-MM-dd 23:59:59"));
            }
            else if (startTime != null && endTime == null)
            {
                startTime = Convert.ToDateTime(startTime.Value.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 23:59:59"));
            }
            else
            {
                startTime = Convert.ToDateTime(startTime.Value.ToString("yyyy-MM-dd 00:00:00"));
                endTime = Convert.ToDateTime(endTime.Value.ToString("yyyy-MM-dd 23:59:59"));
            }
            using (WorkLogContext context = new WorkLogContext())
            {
                var finshStateCountList =context.WorkInfo.Where(p=>p.AddTime >=startTime && p.AddTime<=endTime &&p.UserID==userID)
                                                .GroupBy(g => g.FinshState).Select(s => new { FinshState =s.Key,Count=s.Count()}).ToList();
                var leveCountList = context.WorkInfo.Where(p => p.AddTime >= startTime && p.AddTime <= endTime && p.UserID == userID)
                                           .GroupBy(g => g.Level).Select(s => new { Level = s.Key, Count = s.Count() }).ToList();
                //进行日期分组
                var writeCountLinq=from p in context.WorkInfo
                                   where ( p.AddTime >= startTime && p.AddTime <= endTime && p.UserID == userID)
                                   select p into a
                                   group a by new
                                   {
                                       Time = new
                                       {
                                           a.AddTime.Year,
                                           a.AddTime.Month,
                                           a.AddTime.Day,
                                       },
                                   } into g
                                   select new
                                   {
                                       Count = g.Count(),
                                       Time = string.Concat(string.Concat(string.Concat(g.Key.Time.Year + "-", g.Key.Time.Month), "-"), g.Key.Time.Day),
                                       Year = g.Key.Time.Year,
                                       Month = g.Key.Time.Month,
                                       Day = g.Key.Time.Day,
                                   };
                var templWriteCountList = writeCountLinq.ToList();
                DateTime? tempStartTime = startTime;
                DateTime? tempEndTime = endTime;
                int doneCount = 0;//已填写天数
                int noneCount = 0;//未填写天数
                while (tempStartTime <= tempEndTime)
                {
                    var exist = templWriteCountList.Where(p => p.Year == tempStartTime.Value.Year && p.Month == tempStartTime.Value.Month && p.Day == tempStartTime.Value.Day).ToList();
                    if (exist != null && exist.Count > 0)
                    {
                        doneCount = doneCount + 1;
                    }
                    else 
                    {
                        noneCount = noneCount + 1;
                    }
                    tempStartTime = tempStartTime.Value.AddDays(1.0);
                }
                var writeCountList = new List<dynamic>();
                writeCountList.Add(new {Key="Done",Value=doneCount,Remark= "已填写天数" });
                writeCountList.Add(new { Key = "None", Value = noneCount, Remark = "未填写天数" });

                list.Add(new { Key = "FinshState", Value = finshStateCountList, Remark = "完成情况" });
                list.Add(new { Key = "Leve", Value = leveCountList, Remark = "重要性" });
                list.Add(new { Key = "Write", Value = writeCountList, Remark = "填写情况" });
            }
            return list;
        }

        public dynamic GetEveryDayWriteStatus(DateTime startTime, DateTime endTime, int userID)
        {
            startTime = Convert.ToDateTime(startTime.ToString("yyyy-MM-dd 00:00:00"));
            endTime = Convert.ToDateTime(endTime.ToString("yyyy-MM-dd 23:59:59"));
            using (WorkLogContext context = new WorkLogContext())
            {
                var linq = from a in context.WorkInfo
                           where (a.AddTime >= startTime && a.AddTime <= endTime && a.UserID == userID)
                           group a by new
                           {
                               a.AddTime.Year,
                               a.AddTime.Month,
                               a.AddTime.Day,
                               UserID = a.UserID,
                           }
                           into g
                           select new
                           {
                               Count = g.Count(),
                               Year = g.Key.Year,
                               Month = g.Key.Month,
                               Day = g.Key.Day,
                               UserID=g.Key.UserID
                           };
                var tempStartTime = startTime;
                var tempEndTime = endTime;
                var existList = linq.ToList();
                var list = new List<dynamic>();
                while (tempStartTime <= tempEndTime)
                {
                    var exist = existList.Where(p => p.Year == tempStartTime.Year && p.Month == tempStartTime.Month && p.Day == tempStartTime.Day)
                                         .FirstOrDefault();

                    if (exist != null)
                    {
                        list.Add(new { Year = exist.Year, Month = exist.Month, Day = exist.Day, Count = exist.Count });
                    }
                    else
                    {
                        list.Add(new { Year = tempStartTime.Year, Month = tempStartTime.Month, Day = tempStartTime.Day, Count = 0 });
                    }
                    tempStartTime = tempStartTime.AddDays(1);
                }
                return list;
            }
        }
    }


}
